#pragma once
#include <iostream>
#include <pthread.h>
#include <vector>
#include <list>
#include <exception>
#include "locker.h"
//线程池类
template <typename T>
class threadpool
{

public:
    threadpool(int thread_number = 8, int max_requests = 1000);
    ~threadpool();

    bool append(T *request);
private:
    static void* worker(void*arg);
    void run();
private:
    int m_thread_num;     //线程池
    pthread_t *m_threads; //线程数组

    //请求队列最多允许的请求数量
    int m_max_requests;
    //工作队列
    std::list<T *> m_workqueue;

    //互斥锁
    locker m_queuelocker;

    //信号量用来判断任务是否需要处理

    sem m_queuestat;

    //是否结束线程

    bool m_stop;
};

template <typename T>
threadpool<T>::threadpool(int thread_number, int max_requests) : m_thread_num(thread_number), m_max_requests(max_requests),m_stop(false),m_threads(NULL)
{
    if((thread_number<=0)||max_requests<=0)
    {
        throw std::exception(); 
    }
    m_threads=new pthread_t[m_thread_num];
    //创建num个线程,并肩他们线程分离模式
    for(int i=0;i<thread_number;i++)
    {
        std::cout<<"正在创建第"<<i<<"个线程。。。"<<std::endl;
        if(pthread_create(m_threads+i,NULL,worker,this)!=0)
        {
            delete []m_threads;
            throw std::exception();
        }

        if(pthread_detach(m_threads[i]))
        {
            delete[]m_threads;
            throw std::exception();
        }
    }
    
}

template <typename T>
threadpool<T>::~threadpool()
{

    delete[] m_threads;
    m_stop=true;

}

template <typename T>
bool threadpool<T>::append(T *request)
{

    m_queuelocker.lock();
    if(m_workqueue.size()>m_max_requests)
    {
        m_queuelocker.unlock();
        return false;
    }

    m_workqueue.push_back(request);
    m_queuelocker.unlock();
    m_queuestat.post();
    return true;
}


template<typename T>
void* threadpool<T>::worker(void*arg){
    threadpool*pool=(threadpool*)arg;
    pool->run();

    return pool;
}


template<typename T>
void threadpool<T>::run()
{
    while(!m_stop)
    {
        //信号量有值就不会阻塞，减一
        //没有值就会阻塞
        m_queuestat.wait();
        m_queuelocker.lock();
        if(m_workqueue.empty()){
            m_queuelocker.unlock();
            continue;;
        }
        T* request=m_workqueue.front();
        m_workqueue.pop_front();//删除

        if(!request)
        {
            continue;
        }

        request->process();
    }
}





